package cc.imos.module.allow;

import cc.imos.communal.err.ErrCode;
import cc.imos.communal.err.ErrException;
import cc.imos.entity.*;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.List;

/**
 * 权限检查 <br />
 *
 * Created by asher on 2017/3/26.
 */
@Slf4j
@Component
public class AllowCheck {

    @Autowired
    private AllowRepository allowRepository;

    @Autowired
    private CacheManager cacheManager;

    private List<SysAccount> mAccountList = Lists.newArrayList();
    private List<SysAccountLine> mAccountLineList = Lists.newArrayList();
    private List<SysAccountStatus> mAccountStatusList = Lists.newArrayList();
    private List<SysAction> mActionList = Lists.newArrayList();
    private List<SysStatus> mStatusList = Lists.newArrayList();
    private List<SysStatusAction> mStatusAction = Lists.newArrayList();

    private SysAccount mAccount = null;
    private SysAccountLine mAccountLine = null;
    private SysAction mAction = null;

    private List<SysAccountStatus> mAccountStatuses = Lists.newArrayList();
    private List<SysStatusAction> mStatusActions = Lists.newArrayList();


    public void AllowCheck() {
        mAccountList = allowRepository.findSysAccountList();
        mAccountLineList = allowRepository.findSysAccountLineList();
        mAccountStatusList = allowRepository.findSysAccountStatusList();
        mActionList = allowRepository.findSysActionList();
        mStatusList = allowRepository.findSysStatus();
        mStatusAction = allowRepository.findSysStatusActionList();
    }

    /**
     * <pre>
     * 执行前 > 权限鉴别
     * 改变请求参数
     * </pre>
     *
     * <pre>
     *     1、判断访问功能是否开放
     *     2、判断访问功能是否需要鉴权
     *     3、判断访问账号所属的身份身份符合权限配置
     * </pre>
     * @param servletPath 服务地址
     * @param accessToken 账号令牌
     * @throws ErrException 异常
     */
    public void doCheck(@NotBlank String servletPath, @NotBlank String accessToken) throws ErrException {
        for(SysAction _action: mActionList) {
            if(ObjectUtils.nullSafeEquals(_action.getServletPath(), servletPath)) {
                mAction = _action;
                break;
            }
        }
        if(ObjectUtils.isEmpty(mAction)) {
            throw new ErrException(ErrCode.xxx.name(), "功能未开放");
        }

        boolean check = mAction.getCheck();
        /* 判断功能是否需要鉴权 */
        if(check) { // 需要鉴权
            for (SysAccountLine _line : mAccountLineList) {
                if(ObjectUtils.nullSafeEquals(_line.getAccessToken(), accessToken)) {
                    mAccountLine = _line;
                }
            }
            if(ObjectUtils.isEmpty(mAccountLine)) {
                throw new ErrException(ErrCode.xxx.name(), "请先登录");
            }

            for (SysAccount _account: mAccountList) {
                if(ObjectUtils.nullSafeEquals(_account.getId(), mAccountLine.getAccountId())) {
                    mAccount = _account;
                }
            }

            if(ObjectUtils.isEmpty(mAccount) || !mAccount.getFlag()) {
                throw new ErrException(ErrCode.xxx, "账号无效");
            }

            for (SysAccountStatus _accountStatus: mAccountStatusList) {
                if(ObjectUtils.nullSafeEquals(_accountStatus.getAccountId(), mAccount.getId())) {
                    mAccountStatuses.add(_accountStatus);
                }
            }
            if(ObjectUtils.isEmpty(mAccountStatuses)) {
                throw new ErrException(ErrCode.xxx, "账号无权限");
            }

            for(SysStatusAction _statusAction: mStatusAction) {
                for (SysAccountStatus _accountStatus: mAccountStatuses) {
                    if(ObjectUtils.nullSafeEquals(_statusAction.getStatusId(), _accountStatus.getStatusId())) {
                        mStatusActions.add(_statusAction);
                    }
                }
            }
            if(ObjectUtils.isEmpty(mStatusActions)) {
                throw new ErrException(ErrCode.xxx, "账号权限不足");
            }

            for(SysStatusAction _statusAction: mStatusActions) {
                if(ObjectUtils.nullSafeEquals(_statusAction.getActionId(), mAction.getId())) {
                    return;
                }
            }
            throw new ErrException(ErrCode.xxx, "账号无权访问");
        }
    }
}
